package ren.nearby.http.di.data;


import android.content.Context;
import android.os.Environment;
import android.support.annotation.NonNull;

import com.orhanobut.logger.Logger;

import org.json.JSONObject;
import org.reactivestreams.Subscription;

import java.io.File;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.inject.Inject;
import javax.inject.Singleton;

import io.reactivex.Observable;
import io.reactivex.ObservableSource;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.Function;

import okhttp3.MediaType;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import ren.nearby.bean.beans.CollectionBean;
import ren.nearby.bean.beans.FromAndAction;
import ren.nearby.bean.beans.MusicBean;
import ren.nearby.bean.beans.MusicBeanList;
import ren.nearby.bean.beans.UserBean;
import ren.nearby.http.base.BasePresenter;
import ren.nearby.http.base.BaseView;
import ren.nearby.http.cache.CacheLoader;
import ren.nearby.http.cache.NetworkCache;
import ren.nearby.http.di.HttpApi;
import ren.nearby.http.di.HttpResultBean;
import ren.nearby.http.di.HttpResultBean2;
import ren.nearby.http.di.HttpResultFunc;
import ren.nearby.http.di.HttpsResultBean;
import ren.nearby.http.di.ObserverInterface;
import ren.nearby.http.di.RxResultHelper;
import ren.nearby.http.di.SchedulersCompat;
import ren.nearby.http.progress.FileCallback;
import ren.nearby.http.utils.util.MD5Utils;
import ren.nearby.http.utils.util.PreferencesUtils;
import retrofit2.Call;


/**
 * Created by Angel on 2017/03/02.
 */

@Singleton
public class TasksRemoteDataSource implements TasksDataSource {
    private final HttpApi api;
    private final Context mContext;

    @Inject
    public TasksRemoteDataSource(HttpApi httpApi, Context context) {
        Logger.e("TasksRemoteDataSource-httpApi" + httpApi == null && context == null ? " 1 " : " 0");
        api = httpApi;
        mContext = context;
    }


    private NetworkCache<MusicBeanList> networkCache;

    @Override
    public void login(Map maps, final ResponseCallBack callBack) {
        Logger.e("login...");
        Observable observable = api.login(maps);
        observable.compose(SchedulersCompat.applySchedulers())
                .compose(RxResultHelper.handleResult4(callBack))
                .subscribe(new ObserverInterface<UserBean>() {
                    @Override
                    public void throwError(String msg) {
                        Logger.e("throwError = " + msg);

                    }

                    @Override
                    public void onSubscribe(Disposable d) {
                        Logger.e("onSubscribe = " + d.isDisposed());
                    }

                    @Override
                    public void onNext(UserBean o) {
                        Logger.e("onNext = " + o.toString());
                        PreferencesUtils.putString(mContext, "id", o.getId());
                        PreferencesUtils.putString(mContext, "uuid", o.getPassword());
                        callBack.onDataSuccess(FromAndAction.From.LOGIN, o);
                    }

                    @Override
                    public void onComplete() {
                        Logger.e("onComplete  ");
                    }
                });

    }

    @Override
    public void registered(@NonNull Map map, @NonNull final ResponseCallBack callback) {
        Logger.e("TasksRemoteDataSource - register");
        Observable observable = api.registered(map);
        observable.compose(SchedulersCompat.applySchedulers())
                .compose(RxResultHelper.handleResult4(callback))
                .subscribe(new ObserverInterface<String>() {
                    @Override
                    public void throwError(String msg) {
                        Logger.e("throwError = " + msg);

                    }

                    @Override
                    public void onSubscribe(Disposable d) {
                        Logger.e("onSubscribe = " + d.isDisposed());
                    }

                    @Override
                    public void onNext(String o) {
                        Logger.e("onNext = " + o.toString());
                        callback.onDataSuccess(FromAndAction.From.REGISTERED, o);
                    }

                    @Override
                    public void onComplete() {
                        Logger.e("onComplete  ");
                    }
                });
    }

    @Override
    public void testToken(@NonNull Map map, @NonNull final ResponseCallBack callback) {
        Logger.e("TasksRemoteDataSource - register");
        Observable observable = api.testToken(map);
        observable.compose(SchedulersCompat.applySchedulers())
                .compose(RxResultHelper.handleResult4(callback))
                .subscribe(new ObserverInterface<List<CollectionBean>>() {
                    @Override
                    public void throwError(String msg) {
                        Logger.e("throwError = " + msg);
                        callback.onDataFailure(FromAndAction.From.COLLECTION, msg);
                    }

                    @Override
                    public void onSubscribe(Disposable d) {
                        Logger.e("onSubscribe = " + d.isDisposed());
                    }

                    @Override
                    public void onNext(List<CollectionBean> o) {
                        Logger.e("onNext = " + o.size());
                        callback.onDataSuccess(FromAndAction.From.TESTTOKEN, o);
                    }

                    @Override
                    public void onComplete() {
                        Logger.e("onComplete  ");
                    }
                });

    }

    @Override
    public void collection(@NonNull Map map, @NonNull final ResponseCallBack callback) {
        Logger.e("TasksRemoteDataSource - register");
        Observable observable = api.collection(map);
        observable.compose(SchedulersCompat.applySchedulers())
                .compose(RxResultHelper.handleResult4(callback))
                .subscribe(new ObserverInterface<List<CollectionBean>>() {
                    @Override
                    public void throwError(String msg) {
                        Logger.e("throwError = " + msg);
                        callback.onDataFailure(FromAndAction.From.COLLECTION, msg);
                    }

                    @Override
                    public void onSubscribe(Disposable d) {
                        Logger.e("onSubscribe = " + d.isDisposed());
                    }

                    @Override
                    public void onNext(List<CollectionBean> o) {
                        Logger.e("onNext = " + o.size());
                        callback.onDataSuccess(FromAndAction.From.COLLECTION, o);
                    }

                    @Override
                    public void onComplete() {
                        Logger.e("onComplete  ");
                    }
                });

    }

    @Override
    public void music(Map maps, final ResponseCallBack callBack) {
        Logger.e("TasksRemoteDataSource - login");
        Observable observable = api.search("演员");
      /*  observable
                .compose(SchedulersCompat.applySchedulers())//处理线程
                .compose(RxResultHelper.handleResult())
                .subscribe(new ObserverInterface<List<MusicBean>>() {
                    @Override
                    public void throwError(String msg) {
                        Logger.e(" throwError " + msg);
                    }

                    @Override
                    public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
                        Logger.e(" onSubscribe "+d.isDisposed());
                    }

                    @Override
                    public void onNext(@io.reactivex.annotations.NonNull List<MusicBean> musicBeen) {
                        Logger.e("onNext = " + musicBeen.size());
                    }

                    @Override
                    public void onComplete() {
                        Logger.e(" onComplete ");
                    }
                });*/
        TreeMap<String, String> treeMap = new TreeMap<>();
        treeMap.put("page", 1 + "");
        treeMap.put("limit", 2 + "");
        final String sign = MD5Utils.getAccessToken(treeMap);
        final Observable observable2 = api.search("演员");

  /*      observable2
                .compose(SchedulersCompat.applySchedulers())//处理线程
                .compose(RxResultHelper.handleResult())
                .flatMap(new Function<List<MusicBean>, ObservableSource<MusicBeanList>>() {
                    @Override
                    public ObservableSource<MusicBeanList> apply(@io.reactivex.annotations.NonNull List<MusicBean> musicBeen) throws Exception {
                        Logger.e("来了 ...");
                        MusicBeanList popular = new MusicBeanList(musicBeen);
                        return Observable.fromArray(popular);
                    }
                }).subscribe(new ObserverInterface<MusicBeanList>() {
            @Override
            public void throwError(String msg) {
                Logger.e("throwError = " + msg);
            }

            @Override
            public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
                Logger.e("onSubscribe");
            }

            @Override
            public void onNext(@io.reactivex.annotations.NonNull MusicBeanList musicBeanList) {
                Logger.e("onNext " + musicBeanList.data.size());
            }

            @Override
            public void onComplete() {
                Logger.e("onComplete ");
            }
        });*/
        networkCache = new NetworkCache<MusicBeanList>() {
            @Override
            public Observable<MusicBeanList> get(String key, Class<MusicBeanList> cls) {

                return observable2
                        .compose(SchedulersCompat.applySchedulers())//处理线程
                        .compose(RxResultHelper.handleResult())
                        .flatMap(new Function<List<MusicBean>, ObservableSource<MusicBeanList>>() {
                            @Override
                            public ObservableSource<MusicBeanList> apply(@io.reactivex.annotations.NonNull List<MusicBean> musicBeen) throws Exception {
                                Logger.e("来了 ...");
                                MusicBeanList popular = new MusicBeanList(musicBeen);
                                return Observable.fromArray(popular);
                            }
                        });
            }
        };

        CacheLoader
                .getInstance(mContext)
                .asDataObservable(sign, MusicBeanList.class, networkCache)
                .map(new Function<MusicBeanList, List<MusicBean>>() {
                    @Override
                    public List<MusicBean> apply(@io.reactivex.annotations.NonNull MusicBeanList muiscList) throws Exception {
                        return muiscList.data;
                    }
                }).subscribe(new ObserverInterface<List<MusicBean>>() {

            @Override
            public void throwError(String msg) {
                Logger.e(" throwError = " + msg);

            }


            @Override
            public void onSubscribe(@io.reactivex.annotations.NonNull Disposable d) {
                callBack.onDataStart(1);
                Logger.e(" onSubscribe = " + d.isDisposed());

            }

            @Override
            public void onNext(@io.reactivex.annotations.NonNull List<MusicBean> musicBeen) {
                Logger.e(" onNext = " + musicBeen.size());
                callBack.onDataSuccess(1, musicBeen);
            }

            @Override
            public void onComplete() {
                Logger.e(" onComplete ");
            }
        });


    }

    Call<ResponseBody> responseBodyCall;

    @Override
    public void dowAapk(@NonNull final ResponseCallBack callback) {
        responseBodyCall = api.dowApk();
        String fileStoreDir = Environment.getExternalStorageDirectory().getAbsolutePath() + File
                .separator + "a_nearby";
        String fileStoreName = "sss.apk";
        responseBodyCall.enqueue(new FileCallback(fileStoreDir, fileStoreName) {
            @Override
            public void onSuccess(File file) {
                super.onSuccess(file);
                Logger.e("onSuccess");
                callback.onDataSuccess(FromAndAction.From.TESTDOWAPK, file);

            }

            @Override
            public void progress(long progress, long total) {
                Logger.e("progress");
                callback.onDataStart((int) ((100 * progress) / total));
                Logger.e(String.format("正在下载：(%s/%s)",
                        getFormatSize(progress),
                        getFormatSize(total)));
            }

            @Override
            public void onFailure(Call<ResponseBody> call, Throwable t) {
                Logger.e("onFailure");
                call.cancel();
            }
        });
    }

    public static String getFormatSize(double size) {
        double kiloByte = size / 1024;
        if (kiloByte < 1) {
            return size + "Byte";
        }

        double megaByte = kiloByte / 1024;
        if (megaByte < 1) {
            BigDecimal result1 = new BigDecimal(Double.toString(kiloByte));
            return result1.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "KB";
        }

        double gigaByte = megaByte / 1024;
        if (gigaByte < 1) {
            BigDecimal result2 = new BigDecimal(Double.toString(megaByte));
            return result2.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "MB";
        }

        double teraBytes = gigaByte / 1024;
        if (teraBytes < 1) {
            BigDecimal result3 = new BigDecimal(Double.toString(gigaByte));
            return result3.setScale(2, BigDecimal.ROUND_HALF_UP)
                    .toPlainString() + "GB";
        }
        BigDecimal result4 = new BigDecimal(teraBytes);
        return result4.setScale(2, BigDecimal.ROUND_HALF_UP).toPlainString()
                + "TB";
    }
}
